import cv2
import numpy as np
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.edge.service import Service as EdgeService
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from time import sleep
from PIL import Image

def refresh_captcha(driver, refresh_button_selector):
    """点击刷新验证码按钮"""
    refresh_button = WebDriverWait(driver, 20).until(
        EC.element_to_be_clickable((By.CLASS_NAME, refresh_button_selector))
    )
    refresh_button.click()
    sleep(3)  # 等待验证码加载完成
    print("刷新验证码按钮已点击")
    refresh_button = WebDriverWait(driver, 20).until(
        EC.element_to_be_clickable((By.CLASS_NAME, "geetest_radar_tip"))
    )
    refresh_button.click()
    sleep(3)  # 等待验证码加载完成

def download_captcha_images(driver, bg_image_path, slider_image_path):
    """下载滑块验证码的背景图和滑块图"""
    # 获取背景图
    bg_image = driver.find_element(By.CLASS_NAME, "geetest_canvas_slice")
    slider_image = driver.find_element(By.CLASS_NAME, "geetest_slider_button")

    bg_image.screenshot(bg_image_path)
    slider_image.screenshot(slider_image_path)

def get_gap(bg_path, slider_path, threshold=200):
    """识别缺口位置（改进版）"""
    # 读取灰度图
    bg_img = cv2.imread(bg_path, 0)
    slider_img = cv2.imread(slider_path, 0)

    # 图像预处理（高斯模糊 + 边缘检测）
    bg_img = cv2.GaussianBlur(bg_img, (5, 5), 0)
    slider_img = cv2.GaussianBlur(slider_img, (5, 5), 0)
    bg_edge = cv2.Canny(bg_img, 50, 150)
    slider_edge = cv2.Canny(slider_img, 50, 150)

    # 模板匹配
    result = cv2.matchTemplate(bg_edge, slider_edge, cv2.TM_CCOEFF_NORMED)
    _, max_val, _, max_loc = cv2.minMaxLoc(result)

    # 打印匹配值（调试用）
    print("匹配值：", max_val)

    # 返回缺口的横坐标
    return max_loc[0]

def get_track(distance):
    """生成模拟人的滑动轨迹"""
    track = []
    current = 0
    mid = distance * 4 / 5  # 前段加速，后段减速
    t = 0.2  # 计算周期
    v = 0  # 初始速度

    while current < distance:
        if current < mid:
            a = 2  # 加速度为正
        else:
            a = -3  # 加速度为负

        v0 = v
        v = v0 + a * t
        move = v0 * t + 0.5 * a * (t ** 2)
        current += move
        track.append(round(move))

    return track

def slide_captcha(driver, slider_element, distance):
    """滑动验证码"""
    track = get_track(distance)
    ActionChains(driver).click_and_hold(slider_element).perform()

    for x in track:
        ActionChains(driver).move_by_offset(xoffset=x, yoffset=0).perform()

    sleep(0.5)
    ActionChains(driver).release().perform()

# 主程序
if __name__ == "__main__":
    # 启动 Selenium 浏览器
    edge_service = EdgeService(executable_path='E:\\python\\msedgedriver.exe')

    driver = webdriver.Edge(service=edge_service)
    driver.get("https://mis-toutiao-python.itheima.net/#/")

    # 点击刷新验证码按钮的选择器（需要替换为实际选择器）
    refresh_button_selector = "yzm_btn"

    # 点击刷新按钮并加载验证码
    refresh_captcha(driver, refresh_button_selector)

    # 下载图片
    bg_path = "background.png"
    slider_path = "slider.png"
    download_captcha_images(driver, bg_path, slider_path)

    # 识别缺口位置
    gap = get_gap(bg_path, slider_path)
    print(f"缺口位置：{gap}")

    # 滑动距离（加上偏移修正）
    distance = gap - 6  # 根据实际调整偏移量

    # 获取滑块元素
    slider = driver.find_element(By.CLASS_NAME, "geetest_slider_button")

    # 执行滑动操作
    slide_captcha(driver, slider, distance)

    sleep(5)  # 等待验证结果
    driver.quit()